#include "text.h"

#include <SDL2/SDL_ttf.h>

#include <exception>

struct TextContext {
    SDL_Texture *texture;
    SDL_Renderer *renderer;
    int w, h;
    int align;
};

Text::Text(SDL_Renderer *renderer, const char *msg, TTF_Font *font, SDL_Color color, int align, int wrapLength): context(new TextContext) {
    SDL_Surface *surf = wrapLength > 0 ? TTF_RenderText_Blended_Wrapped(font, msg, color, wrapLength) : TTF_RenderText_Blended(font, msg, color);
    if (surf == nullptr) {
        throw std::bad_exception();
    }
    context->texture = SDL_CreateTextureFromSurface(renderer, surf);
    context->renderer = renderer;
    SDL_FreeSurface(surf);
    SDL_QueryTexture(context->texture, nullptr, nullptr, &context->w, &context->h);
    context->align = align;
}

Text::~Text() {
    SDL_DestroyTexture(context->texture);
    delete context;
}

void Text::getSize(int *w, int *h) {
    *w = context->w;
    *h = context->h;
}

void Text::render(const SDL_Rect &rc) {
    SDL_Rect rrc;
    rrc.w = context->w;
    rrc.h = context->h;
    switch (context->align & AlignHMask) {
        case AlignHRight:
            rrc.x = rc.x + rc.w - rrc.w;
            break;
        case AlignHCenter:
            rrc.x = rc.x + (rc.w - rrc.w) / 2;
            break;
        default:
            rrc.x = rc.x;
            break;
    }
    switch (context->align & AlignVMask) {
        case AlignVBottom:
            rrc.y = rc.y + rc.h - rrc.h;
            break;
        case AlignVCenter:
            rrc.y = rc.y + (rc.h - rrc.h) / 2;
            break;
        default:
            rrc.y = rc.y;
            break;
    }
    SDL_RenderCopy(context->renderer, context->texture, nullptr, &rrc);
}

void Text::render(const SDL_Point &pt) {
    SDL_Rect rrc;
    rrc.w = context->w;
    rrc.h = context->h;
    switch (context->align & AlignHMask) {
        case AlignHRight:
            rrc.x = pt.x - rrc.w;
            break;
        case AlignHCenter:
            rrc.x = pt.x - rrc.w / 2;
            break;
        default:
            rrc.x = pt.x;
            break;
    }
    switch (context->align & AlignVMask) {
        case AlignVBottom:
            rrc.y = pt.y - rrc.h;
            break;
        case AlignVCenter:
            rrc.y = pt.y - rrc.h / 2;
            break;
        default:
            rrc.y = pt.y;
            break;
    }
    SDL_RenderCopy(context->renderer, context->texture, nullptr, &rrc);
}
